package org.agent.aigccore.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.agent.aigccore.model.po.UserInfoPO;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

@Component
public class JwtUtil {
    
    @Resource
    private PasswordEncoder passwordEncoder;
    
    private static PasswordEncoder staticPasswordEncoder;
    
    @PostConstruct
    public void init() {
        staticPasswordEncoder = passwordEncoder;
    }
    
    // 普通令牌有效期 24小时
    private static final long JWT_TOKEN_VALIDITY = 24 * 60 * 60;
    
    // 记住我令牌有效期 7天
    private static final long JWT_TOKEN_VALIDITY_REMEMBER = 7 * 24 * 60 * 60;
    
    // 固定密钥用于跨节点共享（实际项目中应该从配置文件读取）
    private static final String SECRET = "5c3fce2d9e4b5a1a9b7e6c0d3f8a1b9c5e2f8a3d1b6c9e4f7a8b2c5d9e1f3a7b";
    
    // 密钥
    private static final SecretKey SECRET_KEY = Keys.hmacShaKeyFor(SECRET.getBytes());
    
    // 从令牌中获取用户名
    public String getUsernameFromToken(String token) {
        return getClaimFromToken(token, Claims::getSubject);
    }
    
    // 从令牌中获取过期时间
    public Date getExpirationDateFromToken(String token) {
        return getClaimFromToken(token, Claims::getExpiration);
    }
    
    // 从令牌中获取声明
    public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = getAllClaimsFromToken(token);
        return claimsResolver.apply(claims);
    }
    
    // 解析令牌
    private Claims getAllClaimsFromToken(String token) {
        return Jwts.parserBuilder().setSigningKey(SECRET_KEY).build().parseClaimsJws(token).getBody();
    }
    
    // 检查令牌是否过期
    private Boolean isTokenExpired(String token) {
        final Date expiration = getExpirationDateFromToken(token);
        return expiration.before(new Date());
    }
    
    // 生成令牌
    public String generateToken(UserInfoPO userInfoPO, boolean rememberMe) {
        Map<String, Object> claims = new HashMap<>();
        return doGenerateToken(claims, userInfoPO.getUsername(), rememberMe);
    }
    
    // 创建令牌
    private String doGenerateToken(Map<String, Object> claims, String subject, boolean rememberMe) {
        long expirationTime = rememberMe ? JWT_TOKEN_VALIDITY_REMEMBER : JWT_TOKEN_VALIDITY;
        return Jwts.builder()
                .setClaims(claims)
                .setSubject(subject)
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + expirationTime * 1000))
                .signWith(SECRET_KEY)
                .compact();
    }
    
    // 验证令牌
    public Boolean validateToken(String token, UserInfoPO userInfoPO) {
        final String username = getUsernameFromToken(token);
        return (username.equals(userInfoPO.getUsername()) && !isTokenExpired(token));
    }
    
    // 验证密码
    public static boolean verifyPassword(String rawPassword, String encodedPassword) {
        return staticPasswordEncoder.matches(rawPassword, encodedPassword);
    }
}